package handler

import (
	"app-box/api_error"
	"app-box/middleware"
	"app-box/models"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	mgin "github.com/ulule/limiter/v3/drivers/middleware/gin"
)

// Handler 定义Handler类型
type AppHandler interface {
	InitRoute(route gin.IRouter)
}

// SetupRoute 初始化路由
func SetupRoute(engin *gin.Engine) {

	engin.Use(H(HandleError))
	limitDuration := 2 * time.Minute
	engin.Use(middleware.Limit(300, limitDuration, mgin.WithLimitReachedHandler(H(OnLimitReachedHandler(limitDuration)))))
	engin.Use(middleware.CreateRequestID)
	engin.NoRoute(notFoundHandler)

	apiRouter := engin.Group("api")
	apiRouter.Use(middleware.ParseToken())

	openAPIRouter := apiRouter.Group("open")
	fileAPIRouter := apiRouter.Group("file")

	apiRouter.Use(middleware.ParameterSignCheck)

	// 路由表
	routeTable := []AppHandler{
		new(UserHandler),
		new(AppBoxHandler),
	}
	for _, v := range routeTable {
		v.InitRoute(apiRouter)
	}

	// OpenAPI 路由表，不做参数校验
	openAPIRoteTable := []AppHandler{
		new(OpenAPIHandler),
	}
	for _, v := range openAPIRoteTable {
		v.InitRoute(openAPIRouter)
	}
	new(FileHandler).InitRoute(fileAPIRouter)
}

func HandleError(ctx Context) {
	defer func() {
		if err := recover(); err != nil {
			switch errValue := err.(type) {
			case error:
				ctx.Response(errValue)
				ctx.Abort()
				break
			default:
				ctx.Response(api_error.UnknownError(err))
			}
		}
	}()
	ctx.Next()
}

func notFoundHandler(ctx *gin.Context) {
	var result = models.BaseResult{
		Code:    404,
		Message: "Not Found",
		Data:    nil,
	}
	ctx.JSON(http.StatusNotFound, result)
}

func OnLimitReachedHandler(duration time.Duration) HandlerFunc {
	return func(ctx Context) {
		ctx.Response(api_error.ApiRequestLimitError(duration))
		ctx.Abort()
	}
}
